package com.ctsi.commons.util;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 提供propert文件与ResourceBundle支持，因为单一一种都发现在某些环境出问题，但必会都有问题
 * 
 * @author zhangjw
 * 
 */
public final class UtilResource {
	private static final ConcurrentMap<String, Map<String,String>> cache = new ConcurrentHashMap<String, Map<String,String>>();
	/*
	 * public static void main(String[] args) { System.out.println(getResourceName ("com/gentlesoft/cache/scok/cache.properties"));
	 * 
	 * System.out.println(ResourceBundleName( "com/gentlesoft/cache/scok/cache.properties"));
	 * 
	 * //System.out.println(UtilResource.getProperty( "com.itc.commons.util.config.commons.properties","level"));
	 * //System.out.println(UtilResource.getProperty( "com/langchao/commons/util/config/commons.properties","level")); }
	 */
	public String resourceName;

	public UtilResource(String resourceName) {
		this.resourceName = resourceName;
	}

	public String getProperty(final String propertyName) {
		return UtilResource.getProperty(resourceName, propertyName);
	}

	public String getPropertyInCache(String propertyName) {
		return UtilResource.getPropertyInCache(resourceName, propertyName);
	}

	// a.b.c.properties
	private static String getResourceName(final String resourceName, final String ptype) {
		if (resourceName.indexOf(".") < 0)
			return resourceName.concat(getPtype(ptype));
		else {
			String type = UtilFile.getFileType(resourceName);
			if (UtilValidate.isEmpty(type)) {
				return resourceName.replace('.', '/') + getPtype(ptype);
			} else {
				String cutProperties = resourceName.substring(0, resourceName.lastIndexOf("."));
				String tem = cutProperties.replace('.', '/') + "." + type;
				return tem;
			}
		}
	}

	private static final String getPtype(final String ptype) {
		if (UtilValidate.isNotEmpty(ptype)) {
			return ptype;
		}
		return UtilURL.PropertyName;
	}

	/**
	 * 包路径变化
	 * 
	 * @param clazz
	 * @return
	 */
	public static String getResPath(Class<?> clazz) {
		String posion = clazz.getPackage().getName();
		posion = posion.replace('.', '/');
		return posion;
	}

	private static String resourceBundleName(final String resourceName) {

		String result = null;
		if (resourceName.indexOf(UtilURL.PropertyName) < 0) {
			result = resourceName;
		} else {
			result = resourceName.substring(0, resourceName.indexOf(UtilURL.PropertyName));

		}
		if (result.indexOf('/') > 0) {
			result.replace('/', '.');
		}
		return result;

	}

	public static void clearCache() {

		cache.clear();

	}

	public static String getPropertyInCache(final String resourceName,final  String key) {

		assert (resourceName != null);
		String result;
		
        Map<String,String> cacheMap=cache.get(resourceName);
        if(cacheMap!=null){
        	result = cacheMap.get(key);	
        }else{
        	cacheMap=Collections.unmodifiableMap(getPropertyMap(resourceName,false));
        	cache.putIfAbsent(resourceName, cacheMap)	;
        	result = cacheMap.get(key);	
        }

		return result;
	}

	public static final Properties getProperties(final String resourceName) {
		return getPropertiesFromRes(resourceName).p;
	}

	public static final PropertyResource getPropertiesFromRes(final String resourceName) {
		String rName = null;
		InputStream is = null;
		boolean isXml = false;
		try {
			rName = getResourceName(resourceName, null);

			isXml = rName.endsWith(".xml");

			is = UtilResource.class.getClassLoader().getResourceAsStream(rName);
			if (is == null)
				is = Thread.currentThread().getContextClassLoader().getResourceAsStream(rName);
			if (is == null && !isXml) {
				// 查找xml

				rName = getResourceName(resourceName, ".xml");
				is = UtilResource.class.getClassLoader().getResourceAsStream(rName);
				if (is == null)
					is = Thread.currentThread().getContextClassLoader().getResourceAsStream(rName);

			}

		} catch (Throwable e) {
			UtilMisc.closeObjNoExc(is);
			throw new RuntimeException("处理发生错误:" + resourceName, e);
		}
		if (is != null) {
			Properties p = null;
			try {
				p = new Properties();
				if (isXml) {
					p.loadFromXML(is);
				} else {
					p.load(is);
				}
				return new PropertyResource(p, isXml);

			} catch (IOException ex) {
				UtilMisc.closeObjNoExc(is);
				throw new RuntimeException("处理发生错误:" + resourceName, ex);

			} finally {
				UtilMisc.closeObjNoExc(is);
			}
		}
		return new PropertyResource(null, false);

	}

	private static Map<String, String> getProMap(final String resourceName,final  boolean append) {

		Properties p = getProperties(resourceName);
		if (p == null)
			return null;
		Map<String, String> result = new HashMap<String, String>(p.size());
		Enumeration<Object> keyNum = p.keys();
		while (keyNum.hasMoreElements()) {
			String key = (String) keyNum.nextElement();
			String value = (String) p.get(key);

			if (append)
				result.put(resourceName + "." + key, value);
			else
				result.put(key, value);
		}

		return result;
	}

	public static class PropertyResource {
		public final Properties p;
		public final boolean isxml;

		PropertyResource(Properties p, boolean xml) {
			this.p = p;
			this.isxml = xml;
		}
	}

	public static Map<String, String> getPropertyMap(final String resourceName) {
		return getPropertyMap(resourceName, true);
	}

	/**
	 * 
	 * @param resourceName
	 * @param append
	 *            是否增加前缀
	 * @return
	 */
	public static Map<String, String> getPropertyMap(final String resourceName,final  boolean append) {

		Map<String, String> result = getProMap(resourceName, append);

		if (result == null)

		{
			result = getResMap(resourceName, append);
		}

		return result;

	}
	public static Map<String, String> getPropertyMapInCache(final String resourceName ){
		Map<String, String> cacheMap =cache.get(resourceName);
		
        if(cacheMap!=null){
        	return cacheMap;	
        }else{
        	cacheMap=Collections.unmodifiableMap(getPropertyMap(resourceName,false));
        	cache.putIfAbsent(resourceName, cacheMap)	;
        	return  cacheMap;	
        }
 
	}

	private static Map<String, String> getResMap(final String resourceName,final  boolean append) {
		String rName = resourceBundleName(resourceName);
		Map<String, String> result = new HashMap<String, String>();

		ResourceBundle resourceBundle = ResourceBundle.getBundle(rName);
		try {

			Enumeration<String> keyNum = resourceBundle.getKeys();
			while (keyNum.hasMoreElements()) {
				String key = keyNum.nextElement();
				String value = resourceBundle.getString(key);
				if (append)
					result.put(resourceName + "." + key, value);
				else
					result.put(key, value);
			}

		} catch (Exception ex) {
			result = null;

			ex.printStackTrace();
		}
		return result;
	}

	public static Properties getProperties(final URL url) {
		if (url == null)
			throw new RuntimeException("url is null");
		InputStream is = null;
		Properties p = null;
		try {
			boolean isPer = url.getFile().endsWith(UtilURL.PropertyName);
			p = new Properties();
			is = url.openStream();
			if (isPer) {
				p.load(is);
			} else {
				p.loadFromXML(is);
			}
			is.close();

		} catch (IOException ex) {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {

				}
			}

			throw new RuntimeException(ex);

		}
		return p;

	}

	public static String getProperty(final String resourceName,final  String key) {

		String result;

		Properties p = getProperties(resourceName);

		if (p != null) {
			result = p.getProperty(key);
		} else {
			String rName = resourceBundleName(resourceName);
			ResourceBundle resourceBundle = ResourceBundle.getBundle(rName);
			try {

				result = resourceBundle.getString(key);
			} catch (Exception ex) {
				result = null;

				ex.printStackTrace();
			}
		}

		return result;
	}

	public static String getResourceBundleInCache(final String resourceName,final  String key) {

		assert (resourceName != null);

		
		String result;
		
        Map<String,String> cacheMap=cache.get(resourceName);
        if(cacheMap!=null){
        	result = cacheMap.get(key);	
        }else{
        	cacheMap=Collections.unmodifiableMap(getResMap(resourceName,false));
        	cache.putIfAbsent(resourceName, cacheMap)	;
        	result = cacheMap.get(key);	
        }


		return result;
	}

	public static final String getResPath(final Class<?> clazz,final  String resName) {
		String posion = clazz.getPackage().getName();
		posion = posion.replace('.', '/');
		if (resName.startsWith("/")) {
			return posion.concat(resName);
		} else {
			return StringUtil.concatString(posion, "/", resName);
		}

	}
}
